#include "undoRedo.hpp"

#include "qbe/src/ecs/app.hpp"
#include "qbe/src/ecs/bus.hpp"
#include "qbe/src/input/input.hpp"

#include "baseCommand.hpp"
#include "commandManager.hpp"

#include "qlib/all.h"

#include "qbe/src/ui_message/message.h"

#include "qbe/src/select/select.hpp"

namespace qbe::undoRedoT {
void clear_tag(ecs::Query query) {
  // 获取cell和reg
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;

  // 遍历Tag并移除
  auto view_add = reg.view<ObjAddTag>();
  view_add.each([&reg](entt::entity e) { reg.remove<ObjAddTag>(e); });

  auto view_update = reg.view<ObjChangeTag>();
  view_update.each([&reg](entt::entity e) { reg.remove<ObjChangeTag>(e); });

  auto view_delete = reg.view<ObjDeleteTag>();
  view_delete.each([&reg](entt::entity e) { reg.remove<ObjDeleteTag>(e); });
}

void init(ecs::Commands commands, ecs::Query query, ecs::Bus& bus) {
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;

  auto writer = query.get_event_writer<Event>();

  UndoRedoModule module = UndoRedoModule(&reg, query, writer);
  commands.insert_resource(module);
}

void update(ecs::Query query, ecs::Bus& bus) {
  auto& state = query.get_resource<state::State>();
  auto& module = query.get_resource<UndoRedoModule>();
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();

  auto& sele_event_writer = query.get_event_writer<select::Event>();

  if (state.getEditingMode() == state::EditingModeType::Undo) {
    module.switchCell(cell);
    CommandManager* comm = CommandManager::Instance();
    if (comm->CanUndo()) {
      undoRedoT::BaseCommand* pCommand = comm->UndoCommand();
      if (pCommand->checkTag("Add Reference") || pCommand->checkTag("Change Reference") || pCommand->checkTag("Delete Reference")) {
        auto current_lib = query.get_resource<qlib::Library::s_ptr>();
        bus.send<qbe::UiMessage::UpdateFileLisetFromLibrary>(qbe::UiMessage::UpdateFileLisetFromLibrary{current_lib});
      }

      comm->Undo();

      bus.send<qbe::UiMessage::CurrentCellChanged>(qbe::UiMessage::CurrentCellChanged());

      auto view = cell->reg.view<select::SelectTag>();
      view.each([&cell](entt::entity e) { cell->reg.remove<select::SelectTag>(e); });
      sele_event_writer.send({select::Code::SelectUpdate});
      sele_event_writer.send({select::Code::HoverUpdate});
    }
    state.exit();
  }

  if (state.getEditingMode() == state::EditingModeType::Redo) {
    module.switchCell(cell);
    CommandManager* comm = CommandManager::Instance();
    if (comm->CanRedo()) {
      undoRedoT::BaseCommand* pCommand = comm->RedoCommand();
      if (pCommand->checkTag("Add Reference") || pCommand->checkTag("Change Reference") || pCommand->checkTag("Delete Reference")) {
        auto current_lib = query.get_resource<qlib::Library::s_ptr>();
        bus.send<qbe::UiMessage::UpdateFileLisetFromLibrary>(qbe::UiMessage::UpdateFileLisetFromLibrary{current_lib});
      }

      comm->Redo();
      bus.send<qbe::UiMessage::CurrentCellChanged>(qbe::UiMessage::CurrentCellChanged());

      auto view = cell->reg.view<select::SelectTag>();
      view.each([&cell](entt::entity e) { cell->reg.remove<select::SelectTag>(e); });
      sele_event_writer.send({select::Code::SelectUpdate});
      sele_event_writer.send({select::Code::HoverUpdate});
    }
    state.exit();
  }
}

void UndoRedoPlugin::build(ecs::App& app) {
  app.add_stage<InitStage>();
  app.add_stage<UpdateStage>();

  app.init_event<undoRedoT::Event>();

  app.add_systems<InitStage>(init);
  app.add_systems<UpdateStage>(update);
}

}  // namespace qbe::undoRedoT